package comm;

import java.util.ArrayList;

import env.PushableObj;

/**
 * Contains information for scheduling. One-to-one association with pushable
 * objects. Priority is a non-negative number, in [0, 1] by convention; bias is
 * in [0, 1]. If priority is zero, robots ignore object.
 */
public class TaskNode implements Comparable<TaskNode> {
	public PushableObj task;
	public double priority, bias;
	public ArrayList<TaskNode> succ = new ArrayList<TaskNode>(), pred = new ArrayList<TaskNode>();

	public TaskNode(PushableObj t) {
		task = t;
	}

	public void addSucc(TaskNode t) {
		if (!succ.contains(t)) {
			succ.add(t);
			t.addPred(this);
		}
	}

	protected void addPred(TaskNode t) {
		pred.add(t);
	}

	protected void removeSucc(TaskNode t) {
		succ.remove(t);
	}

	protected void removePred(TaskNode t) {
		pred.remove(t);
	}

	// Called when pushable object reaches goal. Transfers own priority to
	// successors and predecessors based on bias. Bias measures how much
	// priority is transferred to successor nodes.
	public void complete() {
		if ((pred.size()+succ.size())==0) return; // Why haven't we gotten a divide by zero yet?
		
		double bPred = priority/(pred.size()+succ.size());
		double bSucc = bPred;
		
		/*
		 * NOTE: It WAS the case that we would redistribute priority
		 * based on bias, and I am keeping the code that does that below
		 * However, at this time, in the current implementation, we
		 * do not distinguish between backward and forward nodes.
		 * 
		 * It is in this sense that it does not make sense to use the bias
		 * calculations.
		 */
		
		
		//double bPred = priority * (1 - bias) / pred.size(), bSucc = priority * bias / succ.size();

		for (TaskNode t : pred) {
			t.priority += bPred;
			t.removeSucc(this);
		}

		for (TaskNode t : succ) {
			t.priority += bSucc;
			t.removePred(this);
		}

		priority = 0;
	}

	// For sorting
	public int compareTo(TaskNode other) {
		double d = priority - other.priority;
		return d > 0 ? -1 : d == 0 ? 0 : 1;
	}

	public boolean equals(Object other) {
		return task.equals(((TaskNode) other).task);
	}

	public String toString() {
		return task.getID();
	}
}
